<?php

namespace App\Services\Stats\Game;

use App\Core\Traits\Numeral;
use App\Exports\Stats\Game\GameExport;
use App\Exports\Stats\Game\GameUsdExport;
use App\Services\Service;
use App\Services\Traits\DatabaseMysql;
use App\Models\Admin\Stats\Settlement\Game as StatsSettlementGame;

class GameService extends Service
{
    use DatabaseMysql, Numeral;

    /**
     * 导出数据
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param \Illuminate\Http\Request $request
     * @param bool $export
     * @return false|void
     */
    private function export($query, $request, bool $export)
    {
        if (!$export) {
            return false;
        }
        // 前端排序
        $this->makeOrderParam($request, $query);
        // 获取数据
        list($collection) = $this->getData($query);
        // 导出文件
        GameExport::collection($collection)->download();
    }

    /**
     * 获取数据和总条数
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return array
     */
    private function getData($query)
    {
        return StatsSettlementGame::dbConnection()->transaction(function () use ($query) {
            // 查询数据
            $collection = $query->getQuery()
                ->selectRaw('SQL_CALC_FOUND_ROWS ' . implode(',', [
                        'game_id', 'currency',
                        'IFNULL(SUM(player_count),0) as player_count',
                        'IFNULL(SUM(doc_count),0) as doc_count',
                        'IFNULL(SUM(amount),0) as amount',
                        'IFNULL(SUM(gain_player),0) as gain_player',
                        'IFNULL(SUM(bet_base),0) as bet_base',
                        'IFNULL(SUM(bet_num),0) as bet_num',
                        "IFNULL(CAST(SUM(usd->'$.amount') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS usd_amount",
                        "IFNULL(CAST(SUM(usd->'$.gain_player') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS usd_gain_player",
                        "IFNULL(CAST(SUM(usd->'$.bet_base') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS usd_bet_base",
                        "IFNULL(CAST(SUM(usd->'$.bet_num') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS usd_bet_num",
                    ]))
                ->groupBy('game_id', 'currency')
                ->orderBy('currency')
                ->get();
            // 数据条数
            $total = (int)StatsSettlementGame::dbConnection()->select("SELECT FOUND_ROWS() as `row_count`")[0]['row_count'];

            return [$collection, $total];
        });
    }

    /**
     * 获取游戏统计列表
     *
     * @param \Illuminate\Http\Request $request
     * @param bool $export
     * @return \Illuminate\Database\Eloquent\Collection[]|int[]|array[]
     */
    public function getList($request, $export = false)
    {
        $query = StatsSettlementGame::query();

        // 筛选【平台】
        $this->makeWhereParamOrg($request, $query);
        // 筛选【平台】【排除】
        $this->makeWhereParamNot($request, 'plat_code_exclude', $query, 'plat_code');
        // 筛选【时间】
        $this->makeWhereParamDatetime($request, $query);
        // 筛选【币种】
        $this->makeWhereParam($request, 'currency', $query);
        // 筛选【币种】【排除】
        $this->makeWhereParamNot($request, 'currency_exclude', $query, 'currency');
        // 筛选【游戏】
        $this->makeWhereParam($request, 'game_id', $query);
        // 筛选【游戏】【排除】
        $this->makeWhereParamNot($request, 'game_id_exclude', $query, 'game_id');

        // 导出数据
        $this->export($query, $request, $export);

        // 统计数据
        $stats = $this->getStats(clone $query);
        // 排序分页
        $this->makeOrderParam($request, $query)->makePaginationParam($request, $query);
        // 获取数据
        list($collection, $total) = $this->getData($query);

        return [
            $collection,
            $total,
            $stats
        ];
    }

    /**
     * 获取统计信息
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return array
     */
    private function getStats($query)
    {
        // USD
        $usd = (clone $query)->getQuery()->selectRaw(implode(',', [
            'IFNULL(SUM(doc_count),0) as doc_count',
            'IFNULL(SUM(player_count),0) as player_count',
            "IFNULL(CAST(SUM(usd->'$.amount') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS amount",
            "IFNULL(CAST(SUM(usd->'$.gain_player') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS gain_player",
            "IFNULL(CAST(SUM(usd->'$.bet_base') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS bet_base",
            "IFNULL(CAST(SUM(usd->'$.bet_num') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS bet_num",
        ]))->first();
        // USD【RTP】
        $usd['rtp'] = $this->makeRtp($usd['bet_num'], $usd['gain_player']);

        // 分币种
        $sts = $query->getQuery()->selectRaw(implode(',', [
            'IFNULL(SUM(player_count),0) as player_count',
            'IFNULL(SUM(doc_count),0) as doc_count',
            'IFNULL(SUM(amount),0) as amount',
            'IFNULL(SUM(gain_player),0) as gain_player',
            'IFNULL(SUM(bet_base),0) as bet_base',
            'IFNULL(SUM(bet_num),0) as bet_num',
            'currency',
        ]))
            ->groupBy('currency')
            ->get();
        // 分币种【RTP】
        $sts->transform(function ($item) {
            return $item + ['rtp' => $this->makeRtp($item['bet_num'], $item['gain_player'])];
        });

        return [
            'usd' => $usd,
            'sts' => $sts,
        ];
    }

    /**
     * 获取游戏统计USD
     *
     * @param \Illuminate\Http\Request $request
     * @param bool $export
     * @return \Illuminate\Database\Eloquent\Collection[]|array[]
     */
    public function getUsd($request, $export = false)
    {
        $query = StatsSettlementGame::query();

        // 筛选【平台】
        $this->makeWhereParamOrg($request, $query);
        // 筛选【平台】【排除】
        $this->makeWhereParamNot($request, 'plat_code_exclude', $query, 'plat_code');
        // 筛选【时间】
        $this->makeWhereParamDatetime($request, $query);
        // 筛选【游戏】
        $this->makeWhereParam($request, 'game_id', $query);
        // 筛选【游戏】【排除】
        $this->makeWhereParamNot($request, 'game_id_exclude', $query, 'game_id');

        // 查询数据
        $collection = (clone $query)->getQuery()->selectRaw(implode(',', [
            'IFNULL(SUM(player_count),0) as player_count',
            'IFNULL(SUM(doc_count),0) as doc_count',
            'game_id',
            "IFNULL(CAST(SUM(usd->'$.amount') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS amount",
            "IFNULL(CAST(SUM(usd->'$.gain_player') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS gain_player",
            "IFNULL(CAST(SUM(usd->'$.bet_base') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS bet_base",
            "IFNULL(CAST(SUM(usd->'$.bet_num') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS bet_num",
        ]))
            ->groupBy('game_id')
            ->orderBy(
                $request->input('order_column', 'doc_count'),
                $request->input('order', 'desc')
            )
            ->get();

        // 导出数据
        if ($export) {
            GameUsdExport::collection($collection)->download();
        }

        // 合计USD
        $stats = $query->getQuery()->selectRaw(implode(',', [
            'IFNULL(SUM(doc_count),0) as doc_count',
            'IFNULL(SUM(player_count),0) as player_count',
            "IFNULL(CAST(SUM(usd->'$.amount') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS amount",
            "IFNULL(CAST(SUM(usd->'$.gain_player') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS gain_player",
            "IFNULL(CAST(SUM(usd->'$.bet_base') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS bet_base",
            "IFNULL(CAST(SUM(usd->'$.bet_num') AS DECIMAL({$this->decimals()},{$this->precision()})),0) AS bet_num",
        ]))->first();
        // USD【RTP】
        $stats['rtp'] = $this->makeRtp($stats['bet_num'], $stats['gain_player']);

        return [
            $collection,
            $stats
        ];
    }
}
